import { applyDecorators, Type } from '@nestjs/common'
import {
  ApiOperation,
  ApiResponse,
  ApiTags,
  ApiParam,
  ApiQuery,
  ApiBody,
  ApiConsumes,
  ApiProduces,
  ApiHeader,
  ApiBearerAuth,
  ApiUnauthorizedResponse,
  ApiForbiddenResponse,
  ApiBadRequestResponse,
  ApiNotFoundResponse,
  ApiInternalServerErrorResponse,
  ApiCreatedResponse,
  ApiOkResponse,
  ApiNoContentResponse,
  getSchemaPath
} from '@nestjs/swagger'
import { PaginationResponseDto, ResponseDto } from '../dto/base.dto'

/**
 * API文档装饰器选项
 */
export interface ApiDocOptions {
  summary: string
  description?: string
  tags?: string[]
  deprecated?: boolean
  auth?: boolean
  responses?: {
    success?: {
      status?: number
      description?: string
      type?: Type<any> | Function | [Function] | string
    }
    error?: {
      badRequest?: boolean
      unauthorized?: boolean
      forbidden?: boolean
      notFound?: boolean
      internalError?: boolean
    }
  }
}

/**
 * 通用API文档装饰器
 * 提供标准的API文档配置
 *
 * @param options API文档选项
 *
 * @example
 * ```typescript
 * @Get(':id')
 * @ApiDoc({
 *   summary: '获取用户详情',
 *   description: '根据用户ID获取用户详细信息',
 *   tags: ['用户管理'],
 *   auth: true,
 *   responses: {
 *     success: {
 *       type: UserResponseDto,
 *       description: '用户信息获取成功'
 *     },
 *     error: {
 *       notFound: true,
 *       unauthorized: true
 *     }
 *   }
 * })
 * findOne(@Param('id') id: string) {}
 * ```
 */
export function ApiDoc(options: ApiDocOptions) {
  const decorators = [
    ApiOperation({
      summary: options.summary,
      description: options.description,
      deprecated: options.deprecated
    })
  ]

  // 添加标签
  if (options.tags && options.tags.length > 0) {
    decorators.push(ApiTags(...options.tags))
  }

  // 添加认证
  if (options.auth) {
    decorators.push(ApiBearerAuth(), ApiUnauthorizedResponse({ description: '未授权访问' }))
  }

  // 添加成功响应
  if (options.responses?.success) {
    const { status = 200, description = '操作成功', type } = options.responses.success

    if (type) {
      if (status === 201) {
        decorators.push(
          ApiCreatedResponse({
            description,
            type: type
          })
        )
      } else if (status === 204) {
        decorators.push(ApiNoContentResponse({ description }))
      } else {
        decorators.push(
          ApiOkResponse({
            description,
            type: type
          })
        )
      }
    } else {
      decorators.push(
        ApiResponse({
          status,
          description
        })
      )
    }
  }

  // 添加错误响应
  if (options.responses?.error) {
    const { badRequest, unauthorized, forbidden, notFound, internalError } = options.responses.error

    if (badRequest) {
      decorators.push(ApiBadRequestResponse({ description: '请求参数错误' }))
    }

    if (unauthorized) {
      decorators.push(ApiUnauthorizedResponse({ description: '未授权访问' }))
    }

    if (forbidden) {
      decorators.push(ApiForbiddenResponse({ description: '权限不足' }))
    }

    if (notFound) {
      decorators.push(ApiNotFoundResponse({ description: '资源不存在' }))
    }

    if (internalError) {
      decorators.push(ApiInternalServerErrorResponse({ description: '服务器内部错误' }))
    }
  }

  return applyDecorators(...decorators)
}

/**
 * 分页API文档装饰器
 * 用于分页查询接口的文档
 *
 * @param dataType 数据类型
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Get()
 * @ApiPagination(UserResponseDto, '获取用户列表', '分页查询用户信息')
 * findAll(@Query() query: QueryUserDto) {}
 * ```
 */
export function ApiPagination<T>(dataType: Type<T>, summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiOkResponse({
      description: '查询成功',
      schema: {
        allOf: [
          { $ref: getSchemaPath(PaginationResponseDto) },
          {
            properties: {
              data: {
                type: 'array',
                items: { $ref: getSchemaPath(dataType) }
              }
            }
          }
        ]
      }
    }),
    ApiQuery({ name: 'page', required: false, description: '页码', example: 1 }),
    ApiQuery({ name: 'limit', required: false, description: '每页数量', example: 10 }),
    ApiQuery({ name: 'sortBy', required: false, description: '排序字段' }),
    ApiQuery({
      name: 'sortOrder',
      required: false,
      description: '排序方向',
      enum: ['ASC', 'DESC']
    }),
    ApiBadRequestResponse({ description: '请求参数错误' })
  )
}

/**
 * 创建API文档装饰器
 * 用于创建资源的接口
 *
 * @param dataType 返回数据类型
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Post()
 * @ApiCreate(UserResponseDto, '创建用户', '创建新用户账户')
 * create(@Body() createUserDto: CreateUserDto) {}
 * ```
 */
export function ApiCreate<T>(dataType: Type<T>, summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiCreatedResponse({
      description: '创建成功',
      type: dataType
    }),
    ApiBadRequestResponse({ description: '请求参数错误' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' })
  )
}

/**
 * 更新API文档装饰器
 * 用于更新资源的接口
 *
 * @param dataType 返回数据类型
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Put(':id')
 * @ApiUpdate(UserResponseDto, '更新用户', '更新用户信息')
 * update(@Param('id') id: string, @Body() updateUserDto: UpdateUserDto) {}
 * ```
 */
export function ApiUpdate<T>(dataType: Type<T>, summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiParam({ name: 'id', description: '资源ID' }),
    ApiOkResponse({
      description: '更新成功',
      type: dataType
    }),
    ApiBadRequestResponse({ description: '请求参数错误' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' }),
    ApiNotFoundResponse({ description: '资源不存在' })
  )
}

/**
 * 删除API文档装饰器
 * 用于删除资源的接口
 *
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Delete(':id')
 * @ApiDelete('删除用户', '根据ID删除用户')
 * remove(@Param('id') id: string) {}
 * ```
 */
export function ApiDelete(summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiParam({ name: 'id', description: '资源ID' }),
    ApiNoContentResponse({ description: '删除成功' }),
    ApiBadRequestResponse({ description: '请求参数错误' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' }),
    ApiNotFoundResponse({ description: '资源不存在' })
  )
}

/**
 * 查询单个资源API文档装饰器
 *
 * @param dataType 返回数据类型
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Get(':id')
 * @ApiFindOne(UserResponseDto, '获取用户详情', '根据ID获取用户信息')
 * findOne(@Param('id') id: string) {}
 * ```
 */
export function ApiFindOne<T>(dataType: Type<T>, summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiParam({ name: 'id', description: '资源ID' }),
    ApiOkResponse({
      description: '查询成功',
      type: dataType
    }),
    ApiBadRequestResponse({ description: '请求参数错误' }),
    ApiNotFoundResponse({ description: '资源不存在' })
  )
}

/**
 * 批量操作API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Delete('batch')
 * @ApiBatch('批量删除用户', '根据ID列表批量删除用户')
 * batchDelete(@Body() dto: BulkOperationDto) {}
 * ```
 */
export function ApiBatch(summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiOkResponse({
      description: '批量操作成功',
      schema: {
        type: 'object',
        properties: {
          success: { type: 'number', description: '成功数量' },
          failed: { type: 'number', description: '失败数量' },
          total: { type: 'number', description: '总数量' }
        }
      }
    }),
    ApiBadRequestResponse({ description: '请求参数错误' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' })
  )
}

/**
 * 文件上传API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 * @param multiple 是否支持多文件上传
 *
 * @example
 * ```typescript
 * @Post('upload')
 * @ApiUpload('上传文件', '上传单个文件')
 * uploadFile(@UploadedFile() file: Express.Multer.File) {}
 * ```
 */
export function ApiUpload(summary: string, description?: string, multiple: boolean = false) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiConsumes('multipart/form-data'),
    ApiBody({
      schema: {
        type: 'object',
        properties: {
          [multiple ? 'files' : 'file']: {
            type: multiple ? 'array' : 'string',
            format: 'binary',
            ...(multiple && { items: { type: 'string', format: 'binary' } })
          }
        }
      }
    }),
    ApiOkResponse({
      description: '上传成功',
      schema: {
        type: 'object',
        properties: {
          url: { type: 'string', description: '文件URL' },
          filename: { type: 'string', description: '文件名' },
          size: { type: 'number', description: '文件大小' },
          mimetype: { type: 'string', description: '文件类型' }
        }
      }
    }),
    ApiBadRequestResponse({ description: '文件格式或大小不符合要求' }),
    ApiUnauthorizedResponse({ description: '未授权访问' })
  )
}

/**
 * 文件下载API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Get('download/:id')
 * @ApiDownload('下载文件', '根据文件ID下载文件')
 * downloadFile(@Param('id') id: string) {}
 * ```
 */
export function ApiDownload(summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiParam({ name: 'id', description: '文件ID' }),
    ApiProduces('application/octet-stream'),
    ApiOkResponse({
      description: '文件下载',
      schema: {
        type: 'string',
        format: 'binary'
      }
    }),
    ApiNotFoundResponse({ description: '文件不存在' }),
    ApiUnauthorizedResponse({ description: '未授权访问' })
  )
}

/**
 * 导出数据API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 * @param format 导出格式
 *
 * @example
 * ```typescript
 * @Get('export')
 * @ApiExport('导出用户数据', '导出用户数据为Excel文件', 'xlsx')
 * exportUsers(@Query() query: ExportUserDto) {}
 * ```
 */
export function ApiExport(summary: string, description?: string, format: string = 'xlsx') {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiProduces('application/octet-stream'),
    ApiHeader({
      name: 'Content-Disposition',
      description: '文件下载头',
      schema: {
        type: 'string',
        example: `attachment; filename="export.${format}"`
      }
    }),
    ApiOkResponse({
      description: '导出成功',
      schema: {
        type: 'string',
        format: 'binary'
      }
    }),
    ApiBadRequestResponse({ description: '导出参数错误' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' })
  )
}

/**
 * 导入数据API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Post('import')
 * @ApiImport('导入用户数据', '从Excel文件导入用户数据')
 * importUsers(@UploadedFile() file: Express.Multer.File) {}
 * ```
 */
export function ApiImport(summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiConsumes('multipart/form-data'),
    ApiBody({
      schema: {
        type: 'object',
        properties: {
          file: {
            type: 'string',
            format: 'binary',
            description: '导入文件（Excel格式）'
          }
        }
      }
    }),
    ApiOkResponse({
      description: '导入成功',
      schema: {
        type: 'object',
        properties: {
          total: { type: 'number', description: '总记录数' },
          success: { type: 'number', description: '成功导入数' },
          failed: { type: 'number', description: '失败数' },
          errors: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                row: { type: 'number', description: '行号' },
                error: { type: 'string', description: '错误信息' }
              }
            }
          }
        }
      }
    }),
    ApiBadRequestResponse({ description: '文件格式错误或数据验证失败' }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' })
  )
}

/**
 * 统计数据API文档装饰器
 *
 * @param summary 接口摘要
 * @param description 接口描述
 *
 * @example
 * ```typescript
 * @Get('stats')
 * @ApiStats('获取用户统计', '获取用户相关统计数据')
 * getStats() {}
 * ```
 */
export function ApiStats(summary: string, description?: string) {
  return applyDecorators(
    ApiOperation({ summary, description }),
    ApiOkResponse({
      description: '统计数据获取成功',
      schema: {
        type: 'object',
        properties: {
          total: { type: 'number', description: '总数' },
          active: { type: 'number', description: '活跃数' },
          inactive: { type: 'number', description: '非活跃数' },
          growth: { type: 'number', description: '增长率' },
          trend: {
            type: 'array',
            items: {
              type: 'object',
              properties: {
                date: { type: 'string', description: '日期' },
                count: { type: 'number', description: '数量' }
              }
            }
          }
        }
      }
    }),
    ApiUnauthorizedResponse({ description: '未授权访问' }),
    ApiForbiddenResponse({ description: '权限不足' })
  )
}

/**
 * 健康检查API文档装饰器
 *
 * @example
 * ```typescript
 * @Get('health')
 * @ApiHealth()
 * healthCheck() {}
 * ```
 */
export function ApiHealth() {
  return applyDecorators(
    ApiOperation({
      summary: '健康检查',
      description: '检查服务健康状态'
    }),
    ApiTags('系统'),
    ApiOkResponse({
      description: '服务正常',
      schema: {
        type: 'object',
        properties: {
          status: { type: 'string', example: 'ok' },
          timestamp: { type: 'string', format: 'date-time' },
          uptime: { type: 'number', description: '运行时间（秒）' },
          version: { type: 'string', description: '版本号' },
          database: { type: 'string', description: '数据库状态' },
          redis: { type: 'string', description: 'Redis状态' }
        }
      }
    })
  )
}
